home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / migcmd / migcmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-09-24  |  16.6 KB  |  638 lines

  1. /*
  2.  * migCmd.c --
  3.  *
  4.  *    Program to manipulate process migration characteristics and
  5.  *    perform other tasks related to migration.
  6.  *
  7.  * Copyright 1988, 1990 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/cmds/migcmd/RCS/migcmd.c,v 1.7 90/09/24 14:39:06 douglis Exp $ SPRITE (Berkeley)";
  19. #endif not lint
  20.  
  21. #include <sprite.h>
  22. #include <sysStats.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <option.h>
  26. #include <proc.h>
  27. #include <spriteTime.h>
  28. #include <kernel/sysSysCall.h>
  29. #include <kernel/trace.h>
  30. #include <kernel/procMigrate.h>
  31. #include <host.h>
  32.  
  33. #include "syscalls.h"
  34.  
  35. /*
  36.  * Variables for options.
  37.  */
  38.  
  39. int allowMigration = 0;
  40. int refuseMigration = 0;
  41. int getStatus = 0;
  42. int getMigStats = 0;
  43. int resetStats = 0;
  44. int input = -1;
  45. int load = -1;
  46. char *importStr = NULL;
  47. char *exportStr = NULL;
  48. int dumpTrace = 0;
  49. int startTrace = 0;
  50. int stopTrace = 0;
  51. int debugLevel = -1;
  52. int newVersion = -1;
  53. int numRecords = 200;
  54.  
  55. Option optionArray[] = {
  56.     {OPT_TRUE, "s", (Address)&getStatus,
  57.      "Print migration version, and conditions under which process migration is allowed."},
  58.     {OPT_TRUE, "S", (Address)&getMigStats,
  59.      "Print migration statistics."},
  60.     {OPT_TRUE, "Z", (Address)&resetStats,
  61.      "Reset migration statistics."},
  62.     {OPT_TRUE, "a", (Address)&allowMigration,
  63.      "Allow all future migrations to this machine (must be root)."},
  64.     {OPT_TRUE, "r", (Address)&refuseMigration,
  65.      "Disallow all future migrations to this machine (must be root)."},
  66.     {OPT_INT, "V", (Address)&newVersion,
  67.      "New migration version to set kernel version to."},
  68.     {OPT_INT, "i", (Address)&input,
  69.      "Whether to ignore idle time for allowing migrations to this machine."},
  70.     {OPT_INT, "l", (Address)&load,
  71.      "Whether to ignore load average for allowing migrations to this machine."},
  72.     {OPT_STRING, "I", (Address)&importStr,
  73.      "what users to allow to import (none, all, root)."},
  74.     {OPT_STRING, "E", (Address)&exportStr,
  75.      "what users to allow to export (none, all, root)."},
  76.     {OPT_TRUE, "p", (Address)&dumpTrace,
  77.      "Print process migration trace records."},
  78.     {OPT_INT, "P", (Address)&numRecords,
  79.      "Number of process migration records to print."},
  80.     {OPT_TRUE, "t", (Address)&startTrace,
  81.      "Enable tracing of process migration."},
  82.     {OPT_TRUE, "T", (Address)&stopTrace,
  83.      "Disable tracing of process migration."},
  84.     {OPT_INT, "d", (Address)&debugLevel,
  85.      "Level to set proc_MigDebugLevel."},
  86. };
  87. /*
  88.  * Constants used by tracing routines:
  89.  *     PROC_NUM_EVENTS - the number of valid trace events for proc.
  90.  */
  91.  
  92. #define PROC_NUM_EVENTS 5
  93.  
  94. /*
  95.  * For imports and exports, we either allow no one to migrate, just root,
  96.  * or everyone.
  97.  */
  98. #define ALLOW_NONE 0
  99. #define ALLOW_ROOT 1
  100. #define ALLOW_ALL 2
  101.  
  102. #define CheckBool(num) if((num) != 0 && (num) != 1) { \
  103.                     Opt_PrintUsage(argv[0], optionArray, \
  104.                            Opt_Number(optionArray)); \
  105.                    }
  106.  
  107. char *myName;
  108. void PrintState();
  109.  
  110. /*
  111.  *----------------------------------------------------------------------
  112.  *
  113.  * main --
  114.  *
  115.  *    Driver.
  116.  *
  117.  * Results:
  118.  *    None.
  119.  *
  120.  * Side effects:
  121.  *    Variable.
  122.  *
  123.  *----------------------------------------------------------------------
  124.  */
  125.  
  126.  
  127. main(argc, argv)
  128.     int argc;
  129.     char *argv[];
  130. {
  131.     ReturnStatus status = SUCCESS;
  132.     char          version[128];
  133.     int Status;
  134.     int changingState = 0;
  135.     int import = -1;
  136.     int export = -1;
  137.     int curVersion;
  138.  
  139.     (void) Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray),
  140.              OPT_ALLOW_CLUSTERING);
  141.  
  142.     myName = argv[0];
  143.     
  144.     if (importStr != NULL) {
  145.     import = CheckString(importStr);
  146.     changingState = 1;
  147.     }
  148.     if (exportStr != NULL) {
  149.     export = CheckString(exportStr);
  150.     changingState = 1;
  151.     }
  152.     if (input != -1) {
  153.     CheckBool(input);
  154.     changingState = 1;
  155.     }
  156.     if (load != -1) {
  157.     CheckBool(load);
  158.     changingState = 1;
  159.     }
  160.              
  161.     if (allowMigration || refuseMigration) {
  162.     changingState = 1;
  163.     }
  164.     
  165.  
  166.     if (debugLevel != -1) {
  167.     status = Sys_Stats(SYS_PROC_MIGRATION, SYS_PROC_MIG_SET_DEBUG,
  168.                (Address) &debugLevel);
  169.     if (status != SUCCESS) {
  170.         Stat_PrintMsg(status, "Sys_Stats (set debug level)");
  171.         exit(status);
  172.     }
  173.     } 
  174.  
  175.     if (changingState || (newVersion != -1) || getStatus) {
  176.     status = Sys_Stats(SYS_PROC_MIGRATION, SYS_PROC_MIG_GET_STATE,
  177.                (Address) &Status);
  178.     if (status != SUCCESS) {
  179.         Stat_PrintMsg(status, "Sys_Stats (getting migration state)");
  180.         exit(status);
  181.     }
  182.     status = Sys_Stats(SYS_PROC_MIGRATION, SYS_PROC_MIG_GET_VERSION,
  183.                (Address) &curVersion);
  184.     if (status != SUCCESS) {
  185.         Stat_PrintMsg(status, "Sys_Stats (getting migration version)");
  186.         exit(status);
  187.     }
  188.     printf("\t\tImport\tExport\tVersion\tIgnore\n");
  189.     PrintState(Status, curVersion, "Current:");
  190.  
  191.     if (changingState) {
  192.         if (allowMigration) {
  193.         Status |= PROC_MIG_IMPORT_ALL;
  194.         } else if (refuseMigration) {
  195.         Status &= ~PROC_MIG_IMPORT_ALL;
  196.         } else if (import != -1) {
  197.         if (import == ALLOW_ALL) {
  198.             Status |= PROC_MIG_IMPORT_ALL;
  199.         } else if (import == ALLOW_NONE) {
  200.             Status &= ~PROC_MIG_IMPORT_ALL;
  201.         } else if (import == ALLOW_ROOT) {
  202.             Status &= ~PROC_MIG_IMPORT_ALL;
  203.             Status |= PROC_MIG_IMPORT_ROOT;
  204.         }
  205.         }
  206.         if (export != -1) {
  207.         if (export == ALLOW_ALL) {
  208.             Status |= PROC_MIG_EXPORT_ALL;
  209.         } else if (export == ALLOW_NONE) {
  210.             Status &= ~PROC_MIG_EXPORT_ALL;
  211.         } else if (export == ALLOW_ROOT) {
  212.             Status &= ~PROC_MIG_EXPORT_ALL;
  213.             Status |= PROC_MIG_EXPORT_ROOT;
  214.         }
  215.         }
  216.         if (input == 0) {
  217.         Status &= ~PROC_MIG_IMPORT_ANYINPUT;
  218.         } else if (input == 1) {
  219.         Status |= PROC_MIG_IMPORT_ANYINPUT;
  220.         }
  221.         if (load == 0) {
  222.         Status &= ~PROC_MIG_IMPORT_ANYLOAD;
  223.         } else if (load == 1) {
  224.         Status |= PROC_MIG_IMPORT_ANYLOAD;
  225.         }
  226.         
  227.         status = Sys_Stats(SYS_PROC_MIGRATION, SYS_PROC_MIG_SET_STATE,
  228.                    (Address) &Status);
  229.         if (status != SUCCESS) {
  230.         Stat_PrintMsg(status, "Sys_Stats (setting migration state)");
  231.         exit(status);
  232.         }
  233.     }
  234.     if (newVersion != -1) {
  235.         status = Sys_Stats(SYS_PROC_MIGRATION, SYS_PROC_MIG_SET_VERSION,
  236.                    (Address) &newVersion);
  237.         if (status != SUCCESS) {
  238.         Stat_PrintMsg(status, "Sys_Stats (setting migration version)");
  239.         exit(status);
  240.         }
  241.     }
  242.     if (changingState || (newVersion != -1)) {
  243.         PrintState(Status, (newVersion != -1) ? newVersion : curVersion,
  244.                "New:\t");
  245.     }
  246.     }
  247.     if (startTrace) {
  248.     status = Sys_Stats(SYS_PROC_TRACE_STATS, SYS_PROC_TRACING_ON,
  249.             (Address) NULL);
  250.     if (status != SUCCESS) {
  251.         (void) fprintf(stderr, "Error %x returned from Test_Stats.\n",
  252.                status);
  253.         Stat_PrintMsg(status, "");
  254.         exit(status);
  255.     }
  256.     }
  257.  
  258.     if (stopTrace) {
  259.     status = Sys_Stats(SYS_PROC_TRACE_STATS, SYS_PROC_TRACING_OFF,
  260.             (Address) NULL);
  261.     if (status != SUCCESS) {
  262.         (void) fprintf(stderr, "Error %x returned from Test_Stats.\n",
  263.                status);
  264.         Stat_PrintMsg(status, "");
  265.         exit(status);
  266.     }
  267.     }
  268.  
  269.     if (dumpTrace) {
  270.     status = PrintMigration();
  271.     }
  272.  
  273.     if (resetStats) {
  274.     status = Sys_Stats(SYS_PROC_MIGRATION, SYS_PROC_MIG_RESET_STATS,
  275.             (Address) NULL);
  276.     if (status != SUCCESS) {
  277.         (void) fprintf(stderr,
  278.                "Error %x returned from Sys_Stats resetting statistics.\n",
  279.                status);
  280.         Stat_PrintMsg(status, "");
  281.         exit(status);
  282.     }
  283.     }
  284.  
  285.     if (getMigStats) {
  286.     status = PrintStats();
  287.     }
  288.  
  289.  
  290.     exit(status);
  291. }
  292.  
  293.  
  294. /*
  295.  *----------------------------------------------------------------------
  296.  *
  297.  * PrintMigration --
  298.  *
  299.  *    Print the most recent process migration trace records.
  300.  *
  301.  * Results:
  302.  *    The return status from Sys_Stats is returned.
  303.  *
  304.  * Side effects:
  305.  *    Trace records are written to stdout.
  306.  *
  307.  *----------------------------------------------------------------------
  308.  */
  309.  
  310.  
  311. int
  312. PrintMigration()
  313. {
  314.     int index;        /* index of current table entry */
  315.     Time baseTime, deltaTime, startTime;    /* Times for print out */
  316.     Address buffer;    /* Buffer for trace records */
  317.     int numRecs;        /* number of records actually copied */
  318.     Trace_Record *traceArray;
  319.     Proc_TraceRecord *procTraceArray;
  320.     register Trace_Record *tracePtr;
  321.     register Proc_TraceRecord *procTracePtr;
  322.     int status;
  323.     static char *flagsArray[] = {"RE", "RS", "HE", "HS", "  "};
  324.     static char *eventArray[] = {"start", "end", "xfer", "call", "migtrap"};
  325.     static char *commandArray[] = {"proc", "vm", "files", "stream", "user",
  326.                  "resume"};
  327.     /*
  328.      * Get a copy of the trace table.
  329.      */
  330.  
  331.     buffer = malloc((unsigned) (sizeof(int) + numRecords *
  332.                 (sizeof(Trace_Record) +
  333.                  sizeof(Proc_TraceRecord))));
  334.     status = Sys_Stats(SYS_PROC_TRACE_STATS, numRecords, buffer);
  335.     if (status != SUCCESS) {
  336.     (void) fprintf(stderr, "Error from Sys_Stats.\n");
  337.     Stat_PrintMsg(status, "");
  338.     return(status);
  339.     }
  340.  
  341.     numRecs = * ((int *) buffer);
  342.     buffer += sizeof(int);
  343.     (void) fprintf(stderr, "Number of records is %d.\n", numRecs);
  344.     (void) fflush(stderr);
  345.     if (numRecs == 0) {
  346.     return(0);
  347.     }
  348.  
  349.     traceArray = (Trace_Record *) buffer;
  350.     procTraceArray = (Proc_TraceRecord *) (buffer + numRecs *
  351.                      sizeof(Trace_Record));
  352.  
  353.  
  354.     (void) printf("\n");
  355. #define PRINT_MIGHEADER() \
  356.     (void) printf("%10s %10s %10s %2s %10s %24s %7s\n", \
  357.     "Time", "Delta", "ProcessID", "HR", "Event", "Call", "Sta")
  358.     PRINT_MIGHEADER();
  359.  
  360.     baseTime = traceArray[0].time;
  361.     startTime = traceArray[0].time;
  362.  
  363.     for (index = 0; index < numRecs; index++) {
  364.     tracePtr = &traceArray[index];
  365.     procTracePtr = &procTraceArray[index];
  366.  
  367.     Time_Subtract(tracePtr->time, startTime, &deltaTime);
  368.     (void) printf(" %3d.%06d",
  369.                deltaTime.seconds,
  370.                deltaTime.microseconds);
  371.     Time_Subtract(tracePtr->time, baseTime, &deltaTime);
  372.     (void) printf(" %3d.%06d",
  373.                deltaTime.seconds,
  374.                deltaTime.microseconds);
  375.     baseTime = tracePtr->time;
  376.  
  377.     if (tracePtr->flags & TRACE_DATA_INVALID) {
  378.         procTracePtr->flags = 4;
  379.         procTracePtr->processID = (Proc_PID) NULL;
  380.     }
  381.     if (((unsigned) procTracePtr->flags) > 3 ||
  382.         ((unsigned) tracePtr->event)  >= PROC_NUM_EVENTS) {
  383.         (void) fprintf(stderr,
  384.                    "Entry %d: invalid flags (%d) or event (%d).\n",
  385.                    index, procTracePtr->flags, tracePtr->event);
  386.         return(-1);
  387.         }
  388.  
  389.     (void) printf("%10x %3s %10s", procTracePtr->processID,
  390.               flagsArray[procTracePtr->flags],
  391.               eventArray[tracePtr->event]);
  392.  
  393.     if (tracePtr->event == PROC_MIGTRACE_COMMAND) {
  394.         (void) printf(" %-10s",
  395.              commandArray[(int) procTracePtr->info.command.type]);
  396.         if (procTracePtr->info.command.data != (ClientData) NIL) {
  397.         (void) printf(" %20d",
  398.                    procTracePtr->info.command.data);
  399.         }
  400.     } else if (tracePtr->event == PROC_MIGTRACE_CALL) {
  401.         (void) printf(" %24s",
  402.              sysCallArray[(int) procTracePtr->info.call.callNumber].name);
  403.         if (!(procTracePtr->flags & PROC_MIGTRACE_START)) {
  404.         (void) printf(" %10x",
  405.                    procTracePtr->info.call.status);
  406.         }
  407.     }
  408.  
  409.     (void) printf("\n");
  410.     }
  411.     PRINT_MIGHEADER();
  412.     return(0);
  413. }
  414.  
  415.  
  416. /*
  417.  *----------------------------------------------------------------------
  418.  *
  419.  * PrintState --
  420.  *
  421.  *    Print the process migration state defined by the status word in
  422.  *    the kernel.
  423.  *
  424.  * Results:
  425.  *    None.
  426.  *
  427.  * Side effects:
  428.  *    Prints to stdout.
  429.  *
  430.  *----------------------------------------------------------------------
  431.  */
  432.  
  433. void
  434. PrintState(state, version, prelude)
  435.     int state;
  436.     int version;
  437.     char *prelude;
  438. {
  439.     int tmp;
  440.     char *import;
  441.     char *export;
  442.     int extra = 0;
  443.  
  444.     tmp = state & PROC_MIG_IMPORT_ALL;
  445.     if (tmp == 0) {
  446.     import = "none";
  447.     } else if (tmp == PROC_MIG_IMPORT_ROOT) {
  448.     import = "root";
  449.     } else{
  450.     import = "all";
  451.     }
  452.     tmp = state & PROC_MIG_EXPORT_ALL;
  453.     if (tmp == 0) {
  454.     export = "none";
  455.     } else if (tmp == PROC_MIG_EXPORT_ROOT) {
  456.     export = "root";
  457.     } else{
  458.     export = "all";
  459.     }
  460.     
  461.     printf("%s\t%4s\t%4s\t%4d\t", prelude, import, export, version);
  462.     if (state & PROC_MIG_IMPORT_ANYLOAD) {
  463.     printf("load");
  464.     extra = 1;
  465.     }
  466.     if (state & PROC_MIG_IMPORT_ANYINPUT) {
  467.     if (extra) {
  468.         printf(", ");
  469.     }
  470.     printf("input");
  471.     }
  472.     printf("\n");
  473. }
  474.  
  475.  
  476.  
  477.  
  478. /*
  479.  *----------------------------------------------------------------------
  480.  *
  481.  * CheckString --
  482.  *
  483.  *    Verify that a string conforms to one of the allowable options
  484.  *    and return that option.
  485.  *
  486.  * Results:
  487.  *    The constant corresponding to the string is returned.
  488.  *
  489.  * Side effects:
  490.  *    If the string is not allowable, an error message is printed and
  491.  *    the process exits.
  492.  *
  493.  *----------------------------------------------------------------------
  494.  */
  495.  
  496. int
  497. CheckString(string)
  498.     char *string;
  499. {
  500.     if(!strcmp(string, "all")) {
  501.     return(ALLOW_ALL);
  502.     }
  503.     if(!strcmp(string, "root")) {
  504.     return(ALLOW_ROOT);
  505.     }
  506.     if(!strcmp(string, "none")) {
  507.     return(ALLOW_NONE);
  508.     }
  509.     Opt_PrintUsage(myName, optionArray, Opt_Number(optionArray));
  510.     exit(1);
  511. }
  512.  
  513.  
  514. /*
  515.  *----------------------------------------------------------------------
  516.  *
  517.  * PrintStats --
  518.  *
  519.  *    Print migration statistics.
  520.  *
  521.  * Results:
  522.  *    The return status from Sys_Stats is returned.
  523.  *
  524.  * Side effects:
  525.  *    Statistics are written to stdout.
  526.  *
  527.  *----------------------------------------------------------------------
  528.  */
  529.  
  530.  
  531. int
  532. PrintStats()
  533. {
  534.     Proc_MigStats stats;        /* statistics */
  535.     int status;
  536.     Time avgTime;
  537.     double time;
  538.     double time2;
  539.     int i;
  540.     Host_Entry *hostPtr;
  541.  
  542.     /*
  543.      * Get a copy of the statistics record.  Make sure it's zeroed in case the
  544.      * kernel provides us with a shorter (older) structure.
  545.      */
  546.  
  547.     bzero((Address) &stats, sizeof(stats));
  548.     status = Sys_Stats(SYS_PROC_MIGRATION, SYS_PROC_MIG_GET_STATS,
  549.                (Address) &stats);
  550.     if (status != SUCCESS) {
  551.     (void) fprintf(stderr, "Error from Sys_Stats.\n");
  552.     Stat_PrintMsg(status, "");
  553.     return(status);
  554.     }
  555.  
  556.     if (stats.statsVersion != PROC_MIG_STATS_VERSION) {
  557.     (void) fprintf(stderr, "Different versions of statistics buffer.\n");
  558.     return(FAILURE);
  559.     }
  560.  
  561. #define PRINT(string, val) printf("%40s\t%d\n", string, stats.val)
  562.  
  563.     PRINT("Number of foreign processes", foreign);
  564.     PRINT("Number of remote processes", remote);
  565.     PRINT("Number of exports", exports);
  566.     PRINT("Number of execs", execs);
  567.     PRINT("Number of imports", imports);
  568.     PRINT("Number of errors", errors);
  569.     PRINT("Number of eviction requests", evictCalls);
  570.     PRINT("Number resulting in evictions", evictsNeeded);
  571.     PRINT("Number of evicted processes", varStats.evictions);
  572.     PRINT("Number voluntary migrations home", migrationsHome);
  573.     PRINT("Number of returns to us", returns);
  574.     PRINT("Number of evictions back to us", evictionsToUs);
  575.     if (stats.evictionsToUs > 0) {
  576.     time = stats.varStats.evictionCPUTime / stats.evictionsToUs;
  577.     } else {
  578.     time = 0;
  579.     }
  580.     printf("%40s\t%7.3f\n", "Average time used after eviction", time);
  581.  
  582.     PRINT("Number of pages written", varStats.pagesWritten);
  583.     if (stats.exports - stats.execs > 0) {
  584.     time = stats.varStats.timeToMigrate /
  585.         (stats.exports + stats.varStats.evictions - stats.execs);
  586.     } else {
  587.     time = 0;
  588.     }
  589.     printf("%40s\t%7.3f\n", "Average time to export", time);
  590.     if (stats.execs > 0) {
  591.     time = stats.varStats.timeToExec / stats.execs;
  592.     } else {
  593.     time = 0;
  594.     }
  595.     printf("%40s\t%7.3f\n", "Average time to exec", time);
  596.  
  597.     if (stats.varStats.evictions > 0) {
  598.     time = stats.varStats.timeToEvict / stats.varStats.evictions;
  599.     } else {
  600.     time = 0;
  601.     }
  602.     printf("%40s\t%7.3f\n", "Average time to evict 1 process", time);
  603.  
  604.     if (stats.evictsNeeded > 0) {
  605.     time = stats.varStats.totalEvictTime / stats.evictsNeeded;
  606.     } else {
  607.     time = 0;
  608.     }
  609.     printf("%40s\t%7.3f\n", "Average time to complete eviction", time);
  610.  
  611.  
  612.     printf("%40s\t%d\n", "Average Kbytes/migration",
  613.        ((stats.exports + stats.varStats.evictions) > 0) ? 
  614.        stats.varStats.rpcKbytes / (stats.exports + stats.varStats.evictions) :
  615.        0);
  616.     printf("%40s\t%d\n", "Average Kbytes/migration",
  617.        ((stats.exports + stats.varStats.evictions) > 0) ? 
  618.        stats.varStats.rpcKbytes / (stats.exports + stats.varStats.evictions) :
  619.        0);
  620.     printf("%40s\t%d/%d (%5.2f%%)\n", "Remote/Total CPU seconds",
  621.        stats.varStats.remoteCPUTime / 10, stats.varStats.totalCPUTime / 10,
  622.        ((double) stats.varStats.remoteCPUTime)/
  623.        stats.varStats.totalCPUTime * 100.0);
  624.     printf("\n%40s\t%s\n", "Host", "count");
  625.     Host_Start();
  626.     while (1) {
  627.     hostPtr = Host_Next();
  628.     if (hostPtr == (Host_Entry *) NULL) {
  629.         break;
  630.     }
  631.     if (stats.hostCounts[hostPtr->id]) {
  632.         printf("%40s\t%d\n", hostPtr->name, stats.hostCounts[hostPtr->id]);
  633.     }
  634.     }
  635.     Host_End();
  636.     return(SUCCESS);
  637. }
  638.